﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Threading;
using System.Windows.Media;
using PhantomMvvmToolkit;

namespace PhantomMvvmToolkitTester
{
    /// <summary>
    /// The root view model of this applicaiton.
    /// </summary>
    public class MainPageViewModel : IPhantomNotifyPropertyChanged, IPhantomCommand
    {
        private string _string1;
        private string _string2;
        private string _currentDelaySetting = "No delay active";
        private readonly SubINotifyPropertyChangedViewModel _subNProp = new SubINotifyPropertyChangedViewModel();
        private DelayEvents CurrentDelayPropertyChangedEvents { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;
        public event EventHandler CanExecuteChanged;

        public bool CanExecute(object parameter)
        {
            var action = (string)parameter;
            switch (action)
            {
                case "StartDelay":
                    return CurrentDelayPropertyChangedEvents == null;
                case "StartDelayOnlyRootObject":
                    return CurrentDelayPropertyChangedEvents == null;
                case "EndDelay":
                    return CurrentDelayPropertyChangedEvents != null;
                case "ThreadUpdate":
                    return true;
                default:
                    return false;
            }
        }

        public void Execute(object parameter)
        {
            var action = (string)parameter;
            switch (action)
            {
                case "StartDelay":
                    CurrentDelayPropertyChangedEvents = this.DelayCanExecuteChangedEvents();
                    CurrentDelaySetting = "Delay root object and all property objects";
                    break;
                case "StartDelayOnlyRootObject":
                    CurrentDelayPropertyChangedEvents = this.DelayCanExecuteChangedEvents(true);
                    CurrentDelaySetting = "Delay root object only";
                    break;
                case "EndDelay":
                    if (CurrentDelayPropertyChangedEvents != null)
                    {
                        CurrentDelayPropertyChangedEvents.Dispose();
                        CurrentDelayPropertyChangedEvents = null;
                    }
                    CurrentDelaySetting = "No delay active";
                    break;
                case "ThreadUpdate":
                    var newThread= new Thread(new ThreadStart(() =>
                    {
                        using (this.ThreadSafeNotifyEvents())
                        {
                            for (int i = 0; i < 10; i++)
                            {
                                String1 = string.Format("Update {0}", i);
                                Thread.Sleep(i * 100);
                                String2 = string.Format("Update {0}", i);
                                Thread.Sleep(i * 200);
                            }
                        }
                    }));
                    newThread.Start();
                    break;
            }
            this.OnCanExecuteChanged(ChangedEventType.IgnoreDelay);
        }

        public string String1
        {
            get { return _string1; }
            set
            {
                if (_string1 != value)
                {
                    _string1 = value;
                    this.OnPropertyChanged("String1");
                }
            }
        }

        public string String2
        {
            get { return _string2; }
            set
            {
                if (_string2 != value)
                {
                    _string2 = value;
                    this.OnPropertyChanged("String2");
                }
            }
        }

        public string CurrentDelaySetting
        {
            get { return _currentDelaySetting; }
            private set
            {
                if (_currentDelaySetting != value)
                {
                    _currentDelaySetting = value;
                    this.OnPropertyChanged("CurrentDelaySetting", ChangedEventType.IgnoreDelay);
                }
            }
        }

        public SubINotifyPropertyChangedViewModel SubNProp { get { return _subNProp; } }

        public void InvokeCanExecuteChanged(EventArgs args)
        {
            if (CanExecuteChanged != null)
                CanExecuteChanged.Invoke(this, args);
        }

        public void InvokePropertyChanged(PropertyChangedEventArgs args)
        {
            if (PropertyChanged != null)
                PropertyChanged.Invoke(this, args);
        }
        
        private bool _BoolValue;
        public bool BoolValue
        {
            get { return _BoolValue; }
            set
            {
                if (_BoolValue != value)
                {
                    _BoolValue = value;
                    this.OnPropertyChanged("BoolValue");
                }
            }
        }
        
        private bool? _NullBoolValue;
        public bool? NullBoolValue
        {
            get { return _NullBoolValue; }
            set
            {
                if (_NullBoolValue != value)
                {
                    _NullBoolValue = value;
                    this.OnPropertyChanged("NullBoolValue");
                }
            }
        }
        
        private int _IntValue;
        public int IntValue
        {
            get { return _IntValue; }
            set
            {
                if (_IntValue != value)
                {
                    _IntValue = value;
                    this.OnPropertyChanged("IntValue");
                }
            }
        }
        
        private int? _NullIntValue;
        public int? NullIntValue
        {
            get { return _NullIntValue; }
            set
            {
                if (_NullIntValue != value)
                {
                    _NullIntValue = value;
                    this.OnPropertyChanged("NullIntValue");
                }
            }
        }
        
        private float _FloatValue;
        public float FloatValue
        {
            get { return _FloatValue; }
            set
            {
                if (_FloatValue != value)
                {
                    _FloatValue = value;
                    this.OnPropertyChanged("FloatValue");
                }
            }
        }
        
        private float? _NullFloatValue;
        public float? NullFloatValue
        {
            get { return _NullFloatValue; }
            set
            {
                if (_NullFloatValue != value)
                {
                    _NullFloatValue = value;
                    this.OnPropertyChanged("NullFloatValue");
                }
            }
        }
        
        private double _DoubleValue;
        public double DoubleValue
        {
            get { return _DoubleValue; }
            set
            {
                if (_DoubleValue != value)
                {
                    _DoubleValue = value;
                    this.OnPropertyChanged("DoubleValue");
                }
            }
        }
        
        private double? _NullDoubleValue;
        public double? NullDoubleValue
        {
            get { return _NullDoubleValue; }
            set
            {
                if (_NullDoubleValue != value)
                {
                    _NullDoubleValue = value;
                    this.OnPropertyChanged("NullDoubleValue");
                }
            }
        }

        private string _Hex3Value;
        public string Hex3Value
        {
            get { return _Hex3Value; }
            set
            {
                if (value != _Hex3Value)
                {
                    _Hex3Value = value;
                    this.OnPropertyChanged("Hex3Value");
                }
            }
        }

        private string _Hex4Value;
        public string Hex4Value
        {
            get { return _Hex4Value; }
            set
            {
                if (value != _Hex4Value)
                {
                    _Hex4Value = value;
                    this.OnPropertyChanged("Hex4Value");
                }
            }
        }

        private string _RBGValue;
        public string RBGValue
        {
            get { return _RBGValue; }
            set
            {
                if (value != _RBGValue)
                {
                    _RBGValue = value;
                    this.OnPropertyChanged("RBGValue");
                }
            }
        }

        private string _RBGAValue;
        public string RBGAValue
        {
            get { return _RBGAValue; }
            set
            {
                if (value != _RBGAValue)
                {
                    _RBGAValue = value;
                    this.OnPropertyChanged("RBGAValue");
                }
            }
        }

        private List<int> _repeaterSource = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        public List<int> RepeaterSource
        {
            get { return _repeaterSource; }
            set
            {
                if (value != _repeaterSource)
                {
                    _repeaterSource = value;
                    this.OnPropertyChanged("RepeaterSource");
                }
            }
        }

    }
}
